package com.common.allCommon;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Arithmetic {
	private static MessageDigest messageDigestMD5 ;
	public MD5Arithmetic() {
		try {
			messageDigestMD5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("No MD5 algorithm.");
		}
	}

	public static synchronized String getMd5(String url) {
		if (url == null) url = "";
		if(messageDigestMD5==null){
			try {
				messageDigestMD5 = MessageDigest.getInstance("MD5");
			} catch (NoSuchAlgorithmException e) {
				throw new RuntimeException("No MD5 algorithm.");
			}
		}
		messageDigestMD5.update(url.getBytes());
		return getHashString(messageDigestMD5);
	}

	private static String getHashString(MessageDigest digest) {
		StringBuilder builder = new StringBuilder();
		for (byte b : digest.digest()) {
			builder.append(Integer.toHexString((b >> 4) & 0xf));
			builder.append(Integer.toHexString(b & 0xf));
		}
		return builder.toString();
	}
	
	 /**
     * TODO: 修改函数实现
     * 对文件计算md5
     * @param path
     * @return
     */
    public static String md5Sum(String path) {
    	String result = "";
    	try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			InputStream is = new FileInputStream(path);
			DigestInputStream dis = new DigestInputStream(is, md);
			while (dis.read() != -1);
			dis.close();
			result = new BigInteger(1, md.digest()).toString(16);
			// Android自带MD5库有问题，首位为0会被截取掉
			if(result.length() == 31){
				return "0" + result;
			}
			return result;
			
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (FileNotFoundException e2) {
			e2.printStackTrace();
		} catch (IOException e3) {
			e3.printStackTrace();
		}
		
		return result;
	}
    
    public static String getMD5OfBytes(byte[] buffer) {
		String result = "";

		MessageDigest complete;
		try {
			complete = MessageDigest.getInstance("MD5");
			byte[] b = complete.digest(buffer);
			for (int i = 0; i < b.length; i++) {
				result += Integer.toString((b[i] & 0xff) + 0x100, 16)
						.substring(1);
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		return result;
	}
    
    /**  
     * 计算文件的MD5  
     * @param fileName 文件的绝对路径  
     * @return  
     * @throws IOException  
     */  
    public static String getFileMD5String(File f) throws IOException{   
        return getFileEncryptString(f,0);   
    }   
    
    public static String getFileSHAString(File f) throws IOException{   
        return getFileEncryptString(f,1);   
    }   
       
    /**  
     * 计算文件的MD5，重载方法  
     * @param file 文件对象  
     * @throws IOException  
     */  
    public static String getFileEncryptString(File file,int type) throws IOException{ 
    	if (messageDigestMD5==null){
    		try {
    			messageDigestMD5 = MessageDigest.getInstance("MD5");
    		} catch (NoSuchAlgorithmException e) {
    			throw new RuntimeException("No MD5 algorithm.");
    		}
    	}
        FileInputStream in = new FileInputStream(file);   
        FileChannel ch = in.getChannel();   
        MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
        in.close();
      	messageDigestMD5.update(byteBuffer);
   	 	return getHashString(messageDigestMD5);   
    }   
}
